Apple的WWDC在昨天圆满结束,期望iPhone6的同学可能很失望,但是对于程序员们,他们又多了好多新玩具。除了成堆的新API,Apple还发布了一款全新的编程语言——Swift。
早就有谣言Apple会想办法替换掉ObjectiveC,但大家都没当回事。可这次,Apple直接放了大招。
并不是Apple喜欢折腾,是ObjectiveC的确不招人喜欢:
- 作为一个C语言的变种,它有较为陡峭的学习曲线
- 缺乏动态特性。虽然新版的ObjectiveC已经非常努力的更新很多看起来很NB的东西,但是这在其他语言确实天生支持的。
- Java直到8才支持lamda,但ObjectiveC的2013年就支持Block了。不过Block的限制太多,而且语法丑陋
- id和instancetype这些东西的产生都是很无奈的,没法彻底解放复杂的类型申明
- 说好的generic和auto-boxing呢
- ...
- [[ObjectievC 的语法] 太罗嗦]
- ...(欢迎补充)
Swift发布后,我第一时间下载了免费的教程,看完了Language Guide后写下我第一篇关于Swift的文章。
可以预料,网上已经有很多文章在说Swift又如何如何的好了。它到底好不好,我们这打个问号。先让说说它十分有特色的地方,顺便附上免费吐槽。
Swift的产生
Swift is a new programming language for iOS and OS X apps that builds on the best of C and Objective-C, without the constraints of C compatibility.
我们解读下Swift编程指南中开篇的第一句话:
- 它是为了编写iOS和OSX的应用而产生的
- 它吸取了C和ObjectiveC的优点
- 它去掉了为了实现对C兼容性而做出的妥协
Swift的产生是面向未来的,并且是冷静分析了当前Apple软件生态圈之后归纳总结出新语言。编程指南的开篇也提到,Apple内部已经使用了Swift多年。
事实上,有LLVM在前,大家应该不难想像Apple可以搞出很多种高级语言出来,反正只要能通过LLVM编译,就能接入Apple的生态体系了。看看隔壁的微软吧,一个.net上面有多少种语言?
Swift也不是Apple的第一次折腾。从Carbon到Cocoa,从MRC到ARC,大家都是含着泪走过来的。其实,Swift也并不能宣判ObjectiveC的死刑,我相信,对于这种翻天覆地的改动,就算一切顺利,也需要一年左右的时间让开发者接受。Apple很可能会观察社区动向,同时对两种语言进行调整,最坏的情况下,有一部分市场的应用仍旧使用ObjectiveC,而另外一部分,尤其是游戏,很可能彻底抛弃ObjectiveC,而使用更敏捷的Swift。
Swift的定位,意味着它有丰富的动态特性,同时拥有静态语言的性能和安全性。你可以通过XCode6的Playground项目进行实验,也可以直接通过Swift编译器进行调试。Swift Compiler位于:
/Applications/Xcode6-Beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift
变量和数据类型
let it be
Swift的所有变量都需要用let或者var声明。这两个关键字的在别的语言广泛存在:ECMAScript(JavaScript、ActionScript)、Go。Swift也并不要求开发者一定需要写明其数据类型,因为编译器有一定能力推断变量的数据类型。
let implicitInteger = 70
let implicitDouble = 70.0
let explicitDouble: Double = 70
注意,这并不是说Swift变成弱类型了。事实上,Swift的变量一旦确定了类型,便不能改变。而且,Swift也不存在隐式转换。例如,如果需要字符串拼接,需要你手动转换:
let widthLabel = label + String(width)
Generics
let emptyDictionary = Dictionary<String, Float>()
ObjectiveC的数据结构最大的诟病就是不支持Generic了。Swift还提供了两个万精油的数据类型:
- AnyObject
- Any
相当于于void*
和id
了,这些东西联合起来可以说是让大家对数据结构的应用更灵活一些了。
数据类型
除了常见的Int、UInt、Float、Double、Bool之外,它还有目前动态语言喜欢使用的Tuple。
var my2dPosition = (20, 20)
var my3dPosition = (20, 10, 50)
这也意味着,支持返回多个数值和Deconstructing了。
var (a,b) = (10,20)
然后就是Range
,一种全闭合,一种半开半闭。
- 1...3
- 1..3
函数
好吧,Swift函数也很难看。它看起来像是Go、Ruby的结合体。但从特性上来讲,Swift的函数是非常优秀的。
- Functions are a first-class type
- 可变的函数列表
- Closure
- 尾部Closure调用
- 捕获当前作用域
- Local and external argument names
这部分将开来讲太复杂了。可以说该有的动态语言特性都有了。
流程控制
更严格的if语句在判断条件时,并不考虑0,而只考虑Boolean。
功能无比强大的switch再也不是鸡肋了:
let somePoint = (1, 1)
switch somePoint {
case (0, 0):
println("(0, 0) is at the origin")
case (_, 0):
println("(\(somePoint.0), 0) is on the x-axis")
case (0, _):
println("(0, \(somePoint.1)) is on the y-axis")
case (-2...2, -2...2):
println("(\(somePoint.0), \(somePoint.1)) is inside the box")
default:
println("(\(somePoint.0), \(somePoint.1)) is outside of the box")
}
// prints "(1, 1) is inside the box
enum、class、struct
把enum
放在这里,是因为Swift里面的enum
的确都是一个类了。
enum Rank: Int {
case Ace = 1
case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
case Jack, Queen, King
func simpleDescription() -> String {
switch self {
case .Ace:
return "ace"
case .Jack:
return "jack"
case .Queen:
return "queen"
case .King:
return "king"
default:
return String(self.toRaw())
}
}
}
面对如此凶残的enum
我们怎么把持的住?
Swift的类继承可能时Swift里最接近C、C++的地方了。无论是它的默认构造函数、解构函数,还是它后面提到的操作符重载都是C的那套思想,只是表现形式换了下。这意味着,这些东西很麻烦。
而同时又有动态语言常有的getter
和setter
那套。
struct Rect {
var origin = Point()
var size = Size()
var center: Point {
get {
let centerX = origin.x + (size.width / 2)
let centerY = origin.y + (size.height / 2)
return Point(x: centerX, y: centerY)
}
set(newCenter) {
origin.x = newCenter.x - (size.width / 2)
origin.y = newCenter.y - (size.height / 2)
}
}
}
每个Property还有两个特殊的observer:
class StepCounter {
var totalSteps: Int = 0 {
willSet(newTotalSteps) {
println("About to set totalSteps to \(newTotalSteps)")
}
didSet {
if totalSteps > oldValue {
println("Added \(totalSteps - oldValue) steps")
}
}
}
}
其他的如Protocol
、Extension
什么的依旧是有的,并且,两者都可以当做Type作为声明变量。
Optional Type
还不知道这个东西该怎么翻译成中文,直接上代码吧:
if let johnsStreet = john.residence?.address?.street {
println("John's street name is \(johnsStreet).")
} else {
println("Unable to retrieve the address.")
}
// prints "Unable to retrieve the address."
一个值要么存在,要么为nil。和if一起使用被成为Optional Binding
。
这恐怕是Swift里最晦涩的概念了。由于Swift里没有指针,而ObjectiveC里一个默认行为就是向nil
对象的调用(发送消息)是没有任何效果,这个特点要完整迁移到Swift里是很困难的。Optional Type的确提供了这个可能, 但这也恐怕是Swift学习成本最大的地方了。
与Cocoa和CocoaTouch的混用
Swift可以和Cocoa、CocoaTouch进行文件级别的混用,也就是说你的项目里可以同时存在这两种文件。在Swift里使用Cocoa的API也是可以的:
let dataViewController = storyboard.instantiateViewControllerWithIdentifier("DataViewController") as DataViewController
Apple通过了复杂的桥接实现了这些,但可以远见之后会有很第三方多框架兼容性问题了。
Swift已经不支持C和C++代码的混用了,要记住这是Swift产生的初衷之一。
期望和展望
个人预测它的流行程度很快会超过Go、Ruby,并与Python并排,之后会稳定上升,最终是否会超过ObjectiveC,甚至接近Java,都需要看Apple的布局了。
XCode6内目前是支持以两种不同的语言来编写应用的,但不知道未来是否会慢慢淘汰ObjectiveC。Apple完全有能力维护两套语言,问题在于它是否需要。在很多领域,开发者早就渴望一种充满动态语言特性的开发语言了,想想iOS上那些内嵌Lua的应用吧。
但是,我觉得Swift并不该像它的前辈那样停留在编写几个iOS或者Mac应用上面,它应该走出来,成为真正意义上的通用语言。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。